package fastcgi

import (
	"log"
	"net/http"
	"strings"
)

func DefaultParam(root string) ParamMiddleware {
	fs := &FileSystemRouter{
		DocRoot:  root,
		Exts:     []string{"php"},
		DirIndex: []string{"index.php"},
	}
	return Group(
		BasicParamsMap,
		MapHeader,
		fs.Router(),
	)
}

func Proxy(root, addr string, req *http.Request) (resp *http.Response, err error) {
	param := NewFastCGIParam()
	DefaultParam(root)(func(params FastCGIParam, req *http.Request) {
	})(param, req)

	//2. 建立cgi.sock连接
	fcgiClient, err := Dial("unix", addr)
	if err != nil {
		return nil, err
	}
	defer fcgiClient.Close()

	//3. 请求数据
	resp, err = fcgiClient.Request(param, req)
	if err != nil {
		return nil, err
	}
	/*body, _ := io.ReadAll(resp.Body)
	fmt.Println("body:", string(body))*/
	return resp, nil
}

func ProxyHttpWriter(root, addr string, req *http.Request, rw http.ResponseWriter) (err error) {
	param := NewFastCGIParam()
	DefaultParam(root)(func(params FastCGIParam, req *http.Request) {
	})(param, req)

	//2. 建立cgi.sock连接
	fcgiClient, err := Dial("unix", addr)
	if err != nil {
		return err
	}
	defer fcgiClient.Close()

	//3. 请求数据
	res, err := fcgiClient.Request(param, req)
	if err != nil {
		return err
	}
	removeHopByHopHeaders(res.Header)

	copyHeader(rw.Header(), res.Header)

	// The "Trailer" header isn't included in the Transport's response,
	// at least for *http.Transport. Build it up from Trailer.
	announcedTrailers := len(res.Trailer)
	if announcedTrailers > 0 {
		trailerKeys := make([]string, 0, len(res.Trailer))
		for k := range res.Trailer {
			trailerKeys = append(trailerKeys, k)
		}
		rw.Header().Add("Trailer", strings.Join(trailerKeys, ", "))
	}

	rw.WriteHeader(res.StatusCode)

	err = fcgiClient.copyResponse(rw, res.Body, fcgiClient.flushInterval(res))
	if err != nil {
		defer res.Body.Close()
		// Since we're streaming the response, if we run into an error all we can do
		// is abort the request. Issue 23643: ReverseProxy should use ErrAbortHandler
		// on read error while copying body.
		if !shouldPanicOnCopyError(req) {
			log.Fatalf("suppressing panic for copyResponse error in test; copy error: %v", err)
			return
		}
		panic(http.ErrAbortHandler)
	}
	res.Body.Close() // close now, instead of defer, to populate res.Trailer

	if len(res.Trailer) > 0 {
		// Force chunking if we saw a response trailer.
		// This prevents net/http from calculating the length for short
		// bodies and adding a Content-Length.
		if fl, ok := rw.(http.Flusher); ok {
			fl.Flush()
		}
	}

	if len(res.Trailer) == announcedTrailers {
		copyHeader(rw.Header(), res.Trailer)
		return
	}

	for k, vv := range res.Trailer {
		k = http.TrailerPrefix + k
		for _, v := range vv {
			rw.Header().Add(k, v)
		}
	}

	return nil
}
